home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-02-14 | 9.1 KB | 245 lines | [TEXT/EDIT] |
- * This function illustrates the use of the XFCN, Letsgo, in
- * calling a MacFortran function from HyperCard. Letsgo does not
- * currently support callbacks from XFCNs. If there's demand, I
- * will add that feature.
-
- * Letsgo can only load your function and the MacFortran runtime
- * library (f77.rl or m81.rl) dynamically. It does not support
- * linking with the MacFortran linker. Thus you will not be able
- * to distribute your function to others who do not own MacFortran
- * and expect them to be able to run it.
-
- * MacFortran will initialize the cursor to the pointer cursor when
- * it starts up. If you find this distasteful, you can change the cursor
- * with toolbox calls from your function or one of its subroutines.
-
- * The usual paths are searched to locate your function and
- * runtime library. These are: the System Folder; the folder
- * containing HyperCard (_not_ the folder containing the calling
- * HyperCard stack); and folders in the root directory called
- * "F77 Overlays" (for the runtime) and "Subroutines" (for your
- * function). Letsgo will not launch your function if it cannot
- * find the runtime library. If it cannot find your function,
- * it will put up the Standard GetFile dialog and ask you to find it.
-
- * Text files will be written to the folder containing HyperCard,
- * _not_ the folder containing the calling HyperCard stack, unless
- * you supply a path name.
-
- * Please note that all data in HyperCard is contained in strings.
- * You can use formatted data reads & writes to an internal file
- * (MacFortran Reference Manual, 8.2.4) to convert values in
- * those strings to integers or reals, etc.
-
- * Neither strings longer than 1k (1024) bytes nor combinations
- * of strings longer than 1k should be written or read using
- * formatted i/o. Likewise, strings longer than 1k bytes should
- * not be passed to MacFortran's internal functions which
- * manipulate strings, such as len. MacFortran will crash if this
- * is done. There is a routine called by this function which
- * illustrates determination of the length of a string of any
- * size. Likewise, there is a routine which will read in strings
- * of arbitrary size from internal files.
-
- * Each argument passed to the function can be up to 32k bytes
- * in length. The length of the argument depends on the length of
- * the corresponding container in HyperCard. Containers in the
- * current version of HyperCard (1.2.2) cannot be larger than
- * 32 k.
-
- * It is not necessary to assign values to the function result.
- * The result container has been filled with spaces before being passed to
- * you. Containers passed to Letsgo are not modified in HyperCard,
- * regardless of what you do to them.
-
- * The last character in a HyperCard container is zero, a byte
- * with no bits set, the null character. The lengths of the arguments
- * passed to your function do not include this last byte. You can
- * shorten the result passed back to HyperCard by stuffing zero in a
- * byte earlier than the last byte. This does not appear to be
- * necessary unless you have written additional data into the result
- * container If you write data past the end of an argument, you will
- * damage HyperCard's heap, possibly with disastrous results
- * (i.e. total corruption of the stack you're working in).
-
- * Thus far I have not crashed a stack by bombing while in an
- * XFCN, which has occurred maybe once or twice (he-he).
- * HyperCard seems to insulate itself fairly well from XFCNs. The most
- * common causes of bombs are argument mismatches in type and number.
-
- * HyperCard (at least in my 1 meg machine) only leaves about 32k
- * of room on the stack. That is the very maximum of room you will
- * have for local variables. It would be safer to use < 25k. You can
- * crash quite easily if you have a heap-stack collision. Letsgo itself
- * uses about 200 bytes of stack space. If you need more space, put your
- * variables in a common block or use the "save" statement. Then they
- * will be allocated on the heap instead of the stack. Named common
- * blocks will be disposed of when the subroutine or function which
- * allocated the block ends; thus, in tight memory situations, you can
- * dispose of large arrays used in subroutines by putting them in named
- * common blocks instead of blank common. You can increase the heap
- * space by changing the "application memory size" of HyperCard in
- * its info box in the Finder.
-
- * The console window may be called up by setting a flag in Letsgo (make
- * the first argument positive). You have to CLOSEWINDOW (_not_
- * DISPOSEWINDOW) the FRONTWINDOW before returning to Hypercard if you
- * call up the console window. If you don't, HyperCard will be very
- * unstable. The console window is suppressed if the first argument
- * is negative.
-
- * If your routine generates an exception which MacFortran can handle,
- * such as divide by zero, MacFortran will write the error message to
- * the front window. When your program hangs, you have to hit the return
- * key to resume execution, if that's possible. If your routine generates an
- * exception when the console window is not open and you don't see the error
- * message, try calling up your routine several more times to try to spot the
- * error message before activating the console window.
-
- * The debugger is not available. You can call your function from a
- * Fortran main program to use the debugger.
-
- * HyperTalk supports three types of array elements:
- * words, delimited by spaces (ascii 32);
- * items, delimited by commas (ascii 44);
- * lines, delimited by carriage returns (ascii 13).
- * These can be combined to support three-dimensional arrays.
- * You could add other array elements for numeric arrays using
- * other non-numeric ascii character delimiters, thereby increasing
- * the possible number of dimensions.
-
- * MacFortran's formatted i/o to internal files with list-directed
- * editing (Fmt=* ) separates output records by carriage returns in
- * implied do loops. Input records under the same conditions need
- * to be separated by spaces. Thus the easiest HyperCard form for
- * one-dimensional input arrays is a set of words. Output arrays are
- * most easily output as a set of lines. Remember to not use formatted
- * i/o for strings longer than 1024 bytes. I do not currently know
- * how otherwise to access separate records in internal files using
- * read and write statements; it undoubtedly can be done by someone
- * more knowledgable about Fortran than I. A method based on pointer
- * manipulation is illustrated in the following function. The method
- * also illustrates how to convert items to words, etc. I also have
- * written an assembly routine which does this located in FiveXFCN.bin
- * in dl 11 of the HyperCard forum of MAUG on CompuServe.
-
- * This function illustrates reading data from a one-dimensional
- * array of words into a real*8 variable. The data is massaged
- * a bit and spat back to HyperCard in the function result. The
- * function also illustrates two methods to determine the length
- * of an argument, and an alternative method for inputting data.
- * Finally, the function writes some data to a text file.
-
- character*(*) function test(a1)
-
- character a1*(*)
-
- integer*4 i,j
- integer*4 lena1
- real*8 temp(4)
-
- open(10,file='testout',status='new')
- write(10,*) a1 !don't try to write uninitialized
- !character vars!
- !don't try to write vars longer
- !than 1k!
-
- * two methods for getting the length of a variable
- lena1 = longle(a1) !method 1
- write(10,*) lena1
- !method 2
- lena1 = len(a1) !don't use this method with
- write(10,*) lena1 !arguments longer than 1k!
-
- * read in some data, massage, and return
- read(a1,*) (temp(i),i=1,3,1) !read from an internal file
- temp(4) = 0
- do (i=1,3,1)
- temp(4) = temp(4) + temp(i)
- repeat
- write(test,*) (temp(i),i=1,4,1) !write to an internal file
- write(10,*) a1, (temp(i),i=1,4,1) !write to disk
-
- * alternative method to read in data
- call input(a1,temp)
- write(10,*) (temp(i),i=1,3,1)
-
- return
-
- end
-
-
- *Function to return the length of a HyperCard container
-
- *n.b. This method works only with HyperCard containers
-
- integer*4 function longle(a1)
-
- implicit none
-
- integer*4 ptra1,i
- integer PTR,toolbx
- parameter (PTR=z'c0000000')
-
- ptra1 = toolbx(PTR,a1)
-
- i = 0
- do
- if (byte(ptra1 + i) = 0) exit !don't count the tailing zero
- i=i+1
- repeat
- longle = i
-
- return
- end
-
- * convert a1 to items and read three real*8 nums from it
-
- * conceptually, this pointer arithmatic is the same as treating
- * each character in the string as a separate element of an array
-
- subroutine input(a1,temp)
-
- implicit none
-
- real*8 temp(4)
- integer*4 ptra1,i,j,PTR,toolbx
- integer*1 bytie
- character a1*(*),itemelement(50)*1, item*50
-
- equivalence (itemelement,item)
-
- parameter (PTR=z'c0000000')
-
- ptra1 = toolbx(PTR,a1)
-
- *convert a1 from words to items for the hell of it
- i = 0
- do (60 times)
- if (byte(ptra1 + i) = 32) byte(ptra1 +i) = 44
- i=i+1
- repeat
-
- *read three real*8 items from a1
- i=1
- j=1
- do
- item = ' '
- do
- bytie = byte(ptra1+i-1)
- if (bytie = 44 .or. bytie = 0) exit !end of item or container
- itemelement(i) = bytie
- i = i+1
- repeat
- read(item,*) temp(j)
- i=i+1
- j=j+1
- if (i=2) j=j-1 !delete empty items
- if (bytie = 0 .or. j=3) exit !end of container or 3 items read
- repeat
-
- return
- end
-
-
-